package com.yunxi.service.localService.impl.sto;

import com.alibaba.cloud.context.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.yunxi.bizToHub.pojo.VehicleInboundVdcVO;
import com.yunxi.bizToHub.pojo.VehicleStockStatusVO;
import com.yunxi.bizToHub.service.VehicleStockManageDubboService;
import com.yunxi.core.page.PageHelperPlus;
import com.yunxi.core.service.ServiceImplPlus;
import com.yunxi.core.util.BeanTools;
import com.yunxi.core.web.DictConstant;
import com.yunxi.dao.sto.*;
import com.yunxi.model.order.PmsVehicleStock;
import com.yunxi.model.sto.*;
import com.yunxi.order.service.OrderCustomerDubboService;
import com.yunxi.order.service.OrderOemManagerDubboService;
import com.yunxi.sat.pojo.SatMessAddVO;
import com.yunxi.service.localService.CodeCreateService;
import com.yunxi.service.localService.sat.SatMessService;
import com.yunxi.service.localService.sto.*;
import com.yunxi.sto.pojo.*;
import com.yunxi.sto.service.VehiclePdiBillDubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 车辆入库计划 服务实现类
 * </p>
 *
 * @author caoYong
 * @since 2019-05-17
 */
@Service
public class StoStockInPlanServiceImpl extends ServiceImplPlus<StoStockInPlanMapper, StoStockInPlan> implements StoStockInPlanService {

    @Autowired
    @Qualifier(value = "stoChangeStorageServiceImpl")
    StoChangeStorageService stoChangeStorageService;

    @Autowired
    @Qualifier(value = "stoManageServiceImpl")
    StoManageService stoManageService;

    @Autowired
    @Qualifier(value = "stoStockInServiceImpl")
    StoStockInService stoStockInService;

    @Autowired
    @Qualifier(value = "vehicleOfflineServiceImpl")
    VehicleOfflineService vehicleOfflineService;


    @Autowired
    @Qualifier(value = "vehicleStockMServiceImpl")
    VehicleStockMService vehicleStockMService;

    @Autowired
    @Qualifier(value = "codeCreateServiceImpl")
    CodeCreateService codeCreateService;

    @Autowired
    @Qualifier(value = "stoStockOutPlanServiceImpl")
    StoStockOutPlanService stoStockOutPlanService;

    @Autowired
    @Qualifier(value = "vehicleStockManageDubboServiceImplBiz")
    VehicleStockManageDubboService vehicleStockManageDubboService;

    @Autowired
    @Qualifier(value = "orderOemManagerDubboServiceImpl")
    OrderOemManagerDubboService orderOemManagerDubboService;

    @Autowired
    @Qualifier(value = "stoVehicleLendOrderServiceImpl")
    StoVehicleLendOrderService stoVehicleLendOrderService;

    @Autowired
    @Qualifier(value = "stoRepairOrderServiceImpl")
    StoRepairOrderService stoRepairOrderService;

    @Autowired
    @Qualifier(value = "stoVrfidHistoryServiceImpl")
    StoVrfidHistoryService stoVrfidHistoryService;

    @Autowired
    @Qualifier(value = "vehiclePdiBillServiceImpl")
    VehiclePdiBillService vehiclePdiBillService;

    @Autowired
    @Qualifier(value = "satMessServiceImpl")
    SatMessService satMessService;

    @Autowired
    OrderCustomerDubboService orderCustomerDubboServiceImpl;

    @Autowired
    VehiclePdiBillDubboService vehiclePdiBillDubboService;

    private static final Logger logger = LoggerFactory.getLogger(StoStockInPlanServiceImpl.class);

    /**
     * 入库完成
     * @param stoStockScanVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(StoStockScanVO stoStockScanVO) throws Exception {
        String partnerCode = stoStockScanVO.getPartnerCode();
        String updateBy = stoStockScanVO.getUpdateBy();
        //1.更新入库计划单状态为 全部入库
        QueryWrapper queryWrapper = new QueryWrapper();
        String vin = stoStockScanVO.getVin();
        queryWrapper.eq("VIN", stoStockScanVO.getVin());
        queryWrapper.eq("BILL_STATE", 5);//单据状态:完成充电
        StoStockInPlan stoStockInPlan = baseMapper.selectOne(queryWrapper);
        if(stoStockInPlan == null || stoStockInPlan.getStockInPlanId() == null ){
            throw new Exception("操作失败,无法根据车辆VIN码"+ stoStockScanVO.getVin()+"找到完成充电的入库计划单!");
        }
        else {
            stoStockInPlan.setBillState("2");//完成入库
            stoStockInPlan.setStockInDate(new Date());//入库时间
            stoStockInPlan.setUpdateBy(updateBy);
            baseMapper.updateById(stoStockInPlan);
        }

        //2.清空车辆上绑定的人员信息RFID_NO
        StoStockScanVO stoStockScanVO1 = new StoStockScanVO();
        stoStockScanVO1.setVin(stoStockScanVO.getVin());
//        stoStockScanVO1.setRfidNo(null); 20190618 U/CY
        baseMapper.bindVehicleState(stoStockScanVO1);

        //3.生成入库单
        StoStockIn stoStockIn = new StoStockIn();
        String stockInNo = codeCreateService.createCode("SI", 4);
        StoStockInVO stoStockInVO = baseMapper.queryStockInInfo(stoStockInPlan.getStockInPlanNo());
        BeanTools.copyProperties(stoStockIn,stoStockInVO);
        stoStockIn.setStockInNo(stockInNo);
        stoStockIn.setStockInPlanNo(stoStockInPlan.getStockInPlanNo());
        stoStockIn.setRfidNo(stoStockScanVO.getRfidNo());
        stoStockIn.setStockInDate(new Date());
        stoStockIn.setCreateBy(updateBy);
        stoStockIn.setUpdateBy(updateBy);
        stoStockInService.saveOrUpdate(stoStockIn);

        //4.更新库位使用状态为占用,解冻
        String storageCode = stoStockInPlan.getStorageCode();
        QueryWrapper<StoManage> queryWrapper1 = new QueryWrapper();
        queryWrapper1.eq("STORAGE_CODE",storageCode);
        StoManage stoManage = stoManageService.getOne(queryWrapper1);
        if(stoManage != null){
            stoManage.setIsPositionFrozen(0);
            stoManage.setStoragePositionState("2");
            stoManageService.updateById(stoManage);
            //插入解冻历史
            vehicleStockMService.newFrozenHis("0",null,storageCode,1);
        }

        //5.更新车辆主数据库存状态为在库
        stoStockOutPlanService.changeVehicleStatus(stoStockScanVO.getVin(),DictConstant.VEHICLE_IN_STOCK,DictConstant.VEHICLE_TURN_STATE_10VDCRK);
        //如果入库类型为借车入库/领用入库,更新借车单状态
        if(stoStockInPlan.getStockInType() != null && (stoStockInPlan.getStockInType().equals("6") || stoStockInPlan.getStockInType().equals("14"))){
            stoStockOutPlanService.changeLendOrderStatus(stoStockScanVO.getVin(),3,4,null,stoStockInPlan.getRfidNo());
        }

        //6.插入或更新库存表
        updateVehicleStockInfo(vin, storageCode,partnerCode,updateBy,stoStockInPlan.getRemark());

        //7.整车VDC入库接口,推送VDC入库信息到SAP
        String stockInType = stoStockInPlan.getStockInType();
        //下线入库
        if(stockInType != null && stockInType.equals("1")){
            VehicleInboundVdcVO vehicleInboundVdcVO = baseMapper.queryVdcStockInInfo(vin);
            if(vehicleInboundVdcVO != null){
                vehicleInboundVdcVO.setBwart(DictConstant.VDC_STOCK_IN);//库房入库
                vehicleStockManageDubboService.vehicleInboundPms2Sap(vehicleInboundVdcVO);
            }
            else{
                logger.debug("操作失败,VDC入库推送信息到SAP为空!");
//                throw new Exception("操作失败,VDC入库推送信息到SAP为空!");
            }
            //9.车辆下线入库,推送信息到订单
            orderOemManagerDubboService.callSapInvokVehicleBatchOrderByVin(vin);
        }

        //8.车辆出入库状态接口,PMS到AIEG
        VehicleStockStatusVO vehicleStockStatusVO = new VehicleStockStatusVO();
        vehicleStockStatusVO.setVin(vin);
        vehicleStockStatusVO.setType(DictConstant.STOCK_IN);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(new Date());
        vehicleStockStatusVO.setOperationDate(format);
        vehicleStockManageDubboService.vehicleStockStatusPms2Tsp(vehicleStockStatusVO);

        //9.推送厂端入库完成到APP
        vehiclePdiBillDubboService.sentMsgToApp(vin,DictConstant.APP_RPNAME_VDC_IN,DictConstant.APP_CODE_02);

        //10 与    orderOemManagerDubboService.callSapInvokVehicleBatchOrderByVin(vin);重复
        //10.查询是否有批售单配车，已配车则发送SAP
        //orderOemManagerDubboService.order2SapByVin(vin);

        //9.入库完成更新VIN到零售订单
//        orderCustomerDubboServiceImpl.updateVin(vin);
    }

    /**
     * 插入或更新车辆库存数据
     * @param vin
     * @param storageCode 库位代码
     */
    private void updateVehicleStockInfo(String vin, String storageCode,String partnerCode,String userId,String remark) {
        QueryWrapper<PmsVehicleStock> queryStock = new QueryWrapper<>();
        queryStock.eq("VIN",vin);
        PmsVehicleStock pmsVehicleStock = vehicleStockMService.getOne(queryStock);
        String storageCodeCk = stoManageService.queryStroageByCode(storageCode);
        if(pmsVehicleStock == null){
            pmsVehicleStock = new PmsVehicleStock();
            pmsVehicleStock.setVin(vin);
        }
        pmsVehicleStock.setStorageLocation(storageCode);//库位代码
        pmsVehicleStock.setStorageCode(storageCodeCk);//仓库代码
        pmsVehicleStock.setVehicleIsFrozen("0");//默认未冻结
        pmsVehicleStock.setStorageStatus(DictConstant.VEHICLE_IN_STOCK);
        pmsVehicleStock.setPartnerCode(partnerCode);
        pmsVehicleStock.setInStockDate(new Date());//入库日期
        pmsVehicleStock.setMemo(remark);//备注
        //设置预计保养时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH,15);
        Date time = calendar.getTime();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(time);
        pmsVehicleStock.setMaintainDate(format);//预计保养时间
        if(pmsVehicleStock.getVehicleId() == null){
            vehicleStockMService.saveOrUpdate(pmsVehicleStock);
        }
        else {
            vehicleStockMService.updateById(pmsVehicleStock);
        }
    }

    @Override
    public void saveAndUpdate(StoStockInPlanVO stoStockInPlanVO) throws Exception {
        Integer isManualIn = stoStockInPlanVO.getIsManualIn();
        String planStockInDate = stoStockInPlanVO.getPlanStockInDate();
        String newStorageCode = stoStockInPlanVO.getStorageCode();
        stoStockInPlanVO.setPlanStockInDate(null);
        StoStockInPlan stoStockInPlan = new StoStockInPlan();
        BeanTools.copyProperties(stoStockInPlan,stoStockInPlanVO);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if(StringUtil.isNotEmpty(planStockInDate)){
            Date parse = simpleDateFormat.parse(planStockInDate);
            stoStockInPlan.setPlanStockInDate(parse);
        }
        //新增时生成入库计划单号
        //录入计划单创建时间
        QueryWrapper<StoStockInPlan> queryWrapper = new QueryWrapper();
        queryWrapper.eq("VIN",stoStockInPlan.getVin());
        queryWrapper.in("BILL_STATE", 0, 4, 5);
        //自动分配司机
        SimpleDateFormat dd = new SimpleDateFormat("dd");
        SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
        Date date = simpleDateFormat1.parse(planStockInDate);
        String day = dd.format(date);
        String dayStr = String.valueOf(Integer.parseInt(day));
        String workMonthStr = simpleDateFormat1.format(date);
        StoDriverVO stoDriverVO1 = new StoDriverVO();
        stoDriverVO1.setDay(Integer.parseInt(day));
        stoDriverVO1.setWorkMonth(workMonthStr);
        List<StoDriverVO> list4 = vehiclePdiBillService.queryTodayDriver(stoDriverVO1);
        if(list4 != null && list4.size() > 0){
            for(StoDriverVO vo : list4){
                String workDays = vo.getWorkDays();
                if(StringUtils.isNotEmpty(workDays)){
                    String[] split = workDays.split(",");
                    Boolean isContains = false;
                    for(String workDay : split){
                        if(workDay.equals(dayStr)){
                            isContains = true;
                            break;
                        }
                    }
                    if(isContains){
                        stoStockInPlan.setRfidNo(vo.getRfid());
                        stoStockInPlan.setRfidDate(new Date());

                        //推送消息给司机
                        SatMessAddVO satMessAddVO = new SatMessAddVO();
                        satMessAddVO.setType("入库");
                        satMessAddVO.setInfo("有一个新的入库计划!");
                        satMessAddVO.setSalesConsultantNo(vo.getUserCode());
                        satMessAddVO.setReceiveRoleCode(DictConstant.USER_ROLE_DRIVER);
                        satMessService.pdaNewMess(satMessAddVO);
                        break;
                    }
                }
                else if((list4 == null || list4.size() ==0) && isManualIn != null && isManualIn.equals(1)){
                    throw new Exception("操作失败,计划入库日期"+planStockInDate+"轮询司机为空!");
                }
            }
        }
        else if((list4 == null || list4.size() ==0) && isManualIn != null && isManualIn.equals(1)){
            throw new Exception("操作失败,计划入库日期"+planStockInDate+"轮询司机为空!");
        }
        if(stoStockInPlan.getStockInPlanId() == null){
            String stockInNo = codeCreateService.createCode("SIP", 4);
            stoStockInPlan.setStockInPlanNo(stockInNo);
            stoStockInPlan.setBillState("0");//单据状态 新建
            stoStockInPlan.setBillCreateTime(new Date());
        }
        //准备入库的单据不允许编辑
        else{
            queryWrapper.ne("STOCK_IN_PLAN_ID",stoStockInPlan.getStockInPlanId());
            String billState = stoStockInPlanVO.getBillState();
            if(billState != null && (billState.equals("1") || billState.equals("3"))){
                throw new Exception("操作失败,准备入库或作废的计划单不允许编辑!");
            }
            //解冻之前所选库位,冻结新选库位
            StoStockInPlan stockInPlan = getById(stoStockInPlan.getStockInPlanId());
            if(stockInPlan != null){
                String storageCode = stockInPlan.getStorageCode();//老库位代码
                if(StringUtil.isNotEmpty(storageCode) && !newStorageCode.equals(storageCode)){
                    QueryWrapper<StoManage> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.eq("STORAGE_CODE",storageCode);
                    StoManage stoManage = stoManageService.getOne(queryWrapper1);
                    if(stoManage != null){
                        stoManage.setIsPositionFrozen(0);
                        stoManageService.saveOrUpdate(stoManage);

                        //插入解冻历史
                        vehicleStockMService.newFrozenHis("0",null,stoManage.getStorageCode(),1);
                    }
                }
            }
        }
        //VIN+单据状态新建校验不可重复创建入库计划
        List<StoStockInPlan> list = baseMapper.selectList(queryWrapper);
        if(list != null && list.size() >0){
            throw new Exception("操作失败,车辆VIN码:"+stoStockInPlan.getVin()+"已存在未完成的入库计划单:"+list.get(0).getStockInPlanNo()+"!");
        }
        //已在库车辆不可再次创建入库计划
        QueryWrapper<PmsVehicleStock> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("VIN",stoStockInPlan.getVin());
        queryWrapper1.eq("STORAGE_STATUS",DictConstant.VEHICLE_IN_STOCK);//在库
        List<PmsVehicleStock> list1 = vehicleStockMService.list(queryWrapper1);
        if(list1 != null && list1.size() > 0){
            QueryWrapper<StoVehicleLendOrder> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("VIN",stoStockInPlan.getVin());
            queryWrapper2.eq("ORDER_STATE",1);
            queryWrapper2.eq("IS_NEED_RETURN",1);
            List<StoVehicleLendOrder> list2 = stoVehicleLendOrderService.list(queryWrapper2);
            if(list2 == null || list2.size() <= 0){
                throw new Exception("操作失败,VIN码:"+stoStockInPlan.getVin()+"已在库,不可创建入库计划!");
            }
        }
        //冻结所选库位
        QueryWrapper<StoManage> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("STORAGE_CODE",newStorageCode);
        StoManage stoManage = stoManageService.getOne(queryWrapper2);
        if(stoManage != null){
            stoManage.setIsPositionFrozen(1);
            stoManageService.saveOrUpdate(stoManage);
            //插入冻结历史
            VehicleStockFrozenVO vehicleStockFrozenVO = new VehicleStockFrozenVO();
            vehicleStockFrozenVO.setFrozenReason("计划入库");
            vehicleStockMService.newFrozenHis("1",vehicleStockFrozenVO,stoManage.getStorageCode(),1);
        }
        saveOrUpdate(stoStockInPlan);
    }

    /**
     *  生成入库单号
     * @param prefix 前缀
     * @return
     */
    private String noCreate(String prefix, Boolean isStockInPlan){
        int length = prefix.length();
        String stockInNo = "";
        String afterFix = "";
        String maxNo = "";
        Date date = new Date();
        SimpleDateFormat yyyyMMdd = new SimpleDateFormat("yyyyMMdd");
        String format = yyyyMMdd.format(date);
        stockInNo = prefix+format;
        if(isStockInPlan){
            maxNo = baseMapper.queryMaxNo(stockInNo);
        }
        else{
            maxNo = stoStockInService.queryMaxNo(stockInNo);
        }
        if(maxNo == null || StringUtil.isEmpty(maxNo)){
            afterFix ="0001";
        }
        else {
            String substring = maxNo.substring(stockInNo.length(),maxNo.length());
            afterFix = String.valueOf(Integer.parseInt(substring) + 1);
            while (afterFix.length() < 4){
                afterFix = ("0"+afterFix);
            }
        }
        stockInNo += afterFix;
        return stockInNo;
    }

    @Override
    public void delAndReset(List<String> list, Integer isDel,String userId)throws Exception {
        if(list != null && list.size() > 0){
            for (String id : list){
                StoStockInPlan stoStockInPlan = baseMapper.selectById(id);
                if(stoStockInPlan != null){
                    String billState = stoStockInPlan.getBillState();
                    if(StringUtils.isNotEmpty(billState) && !billState.equals("0")){
                        if(isDel.equals(1)){
                            throw new Exception("操作失败,只能作废新建的入库计划!");
                        }
                    }
                    //借用,领用,维修类型的入库恢复时,需要校验上级业务单据状态是否为有效状态
                    if(isDel.equals(0)){
                        checkIsValid(stoStockInPlan);
                    }
                    //变更库位冻结状态
                    changeStorageFrozen(isDel, stoStockInPlan);
                    stoStockInPlan.setIsDel(isDel);
                    stoStockInPlan.setBillState("3");
                    saveOrUpdate(stoStockInPlan);
                }
                else{
                    throw new Exception("操作失败,无法根据主键id:"+id+"找到对应入库计划!");
                }
            }
        }
    }


    /**
     * 借用,领用,维修类型的入库恢复时,需要校验上级业务单据状态是否为有效状态
     * @param stoStockInPlan
     * @throws Exception
     */
    private void checkIsValid(StoStockInPlan stoStockInPlan) throws Exception {
        String stockInType = stoStockInPlan.getStockInType();
        String vin = stoStockInPlan.getVin();
        if(StringUtil.isNotEmpty(stockInType) &&(stockInType.equals("4") || stockInType.equals("6") || stockInType.equals("14"))){
            QueryWrapper<StoVehicleLendOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("VIN",vin);
            queryWrapper.ne("ORDER_STATE",5);//排除已作废
            queryWrapper.ne("ORDER_STATE",4);//排除已完成
            List<StoVehicleLendOrder> list1 = stoVehicleLendOrderService.list(queryWrapper);
            QueryWrapper<StoRepairOrder> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq("VIN",vin);
            queryWrapper1.ne("ORDER_STATE","4");//排除已完成
            queryWrapper1.ne("ORDER_STATE","5");//排除已作废
            List<StoRepairOrder> list2 = stoRepairOrderService.list(queryWrapper1);
            if((stockInType.equals("14") || stockInType.equals("6")) && (list1 == null || list1.size() <= 0)){
                throw new Exception("操作失败,不存在有效未完成的借车领用单,无法恢复VIN:"+vin+"相关的入库计划!");
            }
            if(stockInType.equals("4") && (list2 == null || list2.size() <= 0)){
                throw new Exception("操作失败,不存在有效未完成的维修单,无法恢复VIN:"+vin+"相关的入库计划!");
            }
        }
    }

    @Override
    public PageInfo<StoStockInPlanResponseVO> findPageByVO(StoStockInPlanVO stoStockInPlanVO, Integer pageNum, Integer pageSize) throws InvocationTargetException, IllegalAccessException {
        PageInfo<StoStockInPlanResponseVO> pageInfo = pageByVo(stoStockInPlanVO, pageNum, pageSize);
        return  pageInfo;
    }

    /**
     * 逾期入库计划
     * @param stoStockInPlanLateVO
     * @param pageNum
     * @param pageSize
     * @return
     * @throws Exception
     */
    @Override
    public PageInfo<StoStockInPlanLateVO> lateStockInPlan(StoStockInPlanLateVO stoStockInPlanLateVO, Integer pageNum, Integer pageSize) throws Exception {
        PageHelperPlus.startPage(pageNum,pageSize);
        List<StoStockInPlanLateVO> list = baseMapper.lateStockInPlan(stoStockInPlanLateVO);
        PageInfo<StoStockInPlanLateVO> pageInfo = new PageInfo<StoStockInPlanLateVO>(list);
        return pageInfo;
    }

    @Override
    public List<StoStockInPlanResponseVO> export(StoStockInPlanVO stoStockInPlanVO) throws Exception {
        Map map = BeanTools.bean2map(stoStockInPlanVO);
        return baseMapper.queryByList(map);
    }

    /**
     * 将车辆VIN码和车辆RFID绑定,并分配入库目标库位
     * 录入PDA扫描时间
     * @param stoStockScanVO
     * @return
     * @throws Exception
     */
    @Override
    public String bindVehicleRfid(StoStockScanVO stoStockScanVO) throws Exception {
        //校验该车辆RFID未绑定其他车辆
        QueryWrapper<VehicleOffline> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("VEHICLE_RFID",stoStockScanVO.getVehicleRfid());
        queryWrapper1.ne("VIN",stoStockScanVO.getVin());
        List<VehicleOffline> list = vehicleOfflineService.list(queryWrapper1);
        if(list != null && list.size() > 0){
            throw new Exception("操作失败,车辆RFID:"+stoStockScanVO.getVehicleRfid()+"已绑定车辆:"+list.get(0).getVin()+"!");
        }
        //1.绑定车辆RFID到车辆下线主数据
        QueryWrapper<VehicleOffline> queryWrapper = new QueryWrapper();
        queryWrapper.eq("VIN",stoStockScanVO.getVin());
        VehicleOffline vehicleOffline = vehicleOfflineService.getOne(queryWrapper);
        if(vehicleOffline == null){
//            throw new Exception("操作失败,无法根据VIN码:"+stoStockScanVO.getVin()+"找到对应车辆下线记录!");
        }
        else{
            vehicleOffline.setVehicleRfid(stoStockScanVO.getVehicleRfid());
            vehicleOffline.setRfidNo(stoStockScanVO.getRfidNo());
            vehicleOfflineService.updateById(vehicleOffline);
        }

        //2.根据VIN码,单据状态0/新建,找到唯一一条入库计划
        String vin = stoStockScanVO.getVin();
        //通过VIN码找到新建的入库计划单
        StoStockInPlan stockInOrderByVin = getStockInOrderByVin(stoStockScanVO, vin);
        String storageCode = stockInOrderByVin.getStorageCode();
        if(storageCode == null || StringUtil.isEmpty(storageCode)){
            //计划单上库位为空则自动分配空闲库位
            VehiclePdiBillVO vehiclePdiBillVO = new VehiclePdiBillVO();
            List<StoChangeStorageVinListVO> stoChangeStorageVinListVOS = stoChangeStorageService.storageList(vehiclePdiBillVO);
            if(stoChangeStorageVinListVOS == null || stoChangeStorageVinListVOS.size() <= 0){
                throw new Exception("操作失败,没有空闲库位!");
            }
            else{
                //将库位代码写入入库计划单
                storageCode = stoChangeStorageVinListVOS.get(0).getStorageLocation();
                stockInOrderByVin.setStorageCode(storageCode);
//                stockInOrderByVin.setPdaScanTime(new Date());
                baseMapper.updateById(stockInOrderByVin);
                //更新库位状态为占用
                //调整为,入库完成前,冻结该库位,完成入库则更新库位使用状态为占用,解冻
                QueryWrapper queryWrapper2 = new QueryWrapper();
                queryWrapper2.eq("STORAGE_CODE",storageCode);
                StoManage stoManage = stoManageService.getOne(queryWrapper2);
                if(stoManage != null){
                    stoManage.setIsPositionFrozen(1);
                    stoManageService.updateById(stoManage);
                }
            }
        }
        String storagFullName = stoManageService.getStorageFullName(storageCode);//仓库全名

        //3.新增车辆RFID绑定记录
        newBindHistory(stoStockScanVO);
        return storagFullName;
    }

    /**
     * 开始入库
     * @param stoStockScanVO
     * @throws Exception
     */
    @Override
    public void beginStockIn(StoStockScanVO stoStockScanVO) throws Exception {
        String vin = stoStockScanVO.getVin();
        //通过VIN码找到新建的入库计划单
        StoStockInPlan stockInOrderByVin = getStockInOrderByVin(stoStockScanVO, vin);
        //校验计划入库日期和当前日期是否匹配
        Date planStockInDate = stockInOrderByVin.getPlanStockInDate();
        //20190921屏蔽入库计划日期验证
        //    checkPlanStockInDate(planStockInDate,DictConstant.STOCK_IN);

        stockInOrderByVin.setBillState("1");//开始入库
        stockInOrderByVin.setRfidNo(stoStockScanVO.getRfidNo());
        baseMapper.updateById(stockInOrderByVin);

        QueryWrapper<VehicleOffline> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",vin);
        VehicleOffline one = vehicleOfflineService.getOne(queryWrapper);
        if(one != null){
            one.setRfidNo(stoStockScanVO.getRfidNo());
            vehicleOfflineService.updateById(one);
        }
    }

    /**
     * 校验计划出入库日期和当前日期是否匹配
     * @param planDate
     * @throws Exception
     */
    @Override
    public void checkPlanStockInDate(Date planDate,Integer type) throws Exception {
        if(planDate != null){
            Date date = new Date();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(planDate);
            planDate = simpleDateFormat.parse(simpleDateFormat.format(planDate));
            date = simpleDateFormat.parse(simpleDateFormat.format(date));
            int i = planDate.compareTo(date);
            if(i != 0){
                if(type.equals(DictConstant.STOCK_IN)){
                    throw new Exception("操作失败,计划入库日期为:"+format+"!");
                }
                else if(type.equals(DictConstant.STOCK_OUT)){
                    throw new Exception("操作失败,计划出库日期为:"+format+"!");
                }
            }
        }
    }

    /**
     * 根据rfid查询六个月内出入库数量
     * @param rfidNo
     * @return
     * @throws Exception
     */
    @Override
    public List<StoStockInOutReportListVO> stockInOutCount(String rfidNo) throws Exception {
        StoStockInOutReportVO stoStockInOutReportVO = baseMapper.stockInOutCount(rfidNo);
        List<StoStockInOutReportListVO> list = new ArrayList<>();
        if(stoStockInOutReportVO != null){
            for (int i = 1;i<=6;i++){
                StoStockInOutReportListVO vo = new StoStockInOutReportListVO();
                switch (i){
                    case 1:
                        vo.setMonth(stoStockInOutReportVO.getNowMonth());
                        vo.setInCount(stoStockInOutReportVO.getNowIn());
                        vo.setOutCount(stoStockInOutReportVO.getNowOut());
                        break;
                    case 2:
                        vo.setMonth(stoStockInOutReportVO.getLastOneMonth());
                        vo.setInCount(stoStockInOutReportVO.getLastOneIn());
                        vo.setOutCount(stoStockInOutReportVO.getLastOneOut());
                        break;
                    case 3:
                        vo.setMonth(stoStockInOutReportVO.getLastTwoMonth());
                        vo.setInCount(stoStockInOutReportVO.getLastTwoIn());
                        vo.setOutCount(stoStockInOutReportVO.getLastTwoOut());
                        break;
                    case 4:
                        vo.setMonth(stoStockInOutReportVO.getLastThreeMonth());
                        vo.setInCount(stoStockInOutReportVO.getLastThreeIn());
                        vo.setOutCount(stoStockInOutReportVO.getLastThreeOut());
                        break;
                    case 5:
                        vo.setMonth(stoStockInOutReportVO.getLastFourMonth());
                        vo.setInCount(stoStockInOutReportVO.getLastFourIn());
                        vo.setOutCount(stoStockInOutReportVO.getLastFourOut());
                        break;
                    case 6:
                        vo.setMonth(stoStockInOutReportVO.getLastFiveMonth());
                        vo.setInCount(stoStockInOutReportVO.getLastFiveIn());
                        vo.setOutCount(stoStockInOutReportVO.getLastFiveOut());
                        break;
                }
                list.add(vo);
            }
        }
        return list;
    }

    @Override
    public List<StoStockInPlanVO> planListByVin(String vin,String rfid) throws Exception {
        StoStockScanVO stoStockScanVO = new StoStockScanVO();
        stoStockScanVO.setVin(vin);
        stoStockScanVO.setRfidNo(rfid);
        List<StoStockInPlanVO> voList = baseMapper.planListByVin(stoStockScanVO);
        /*QueryWrapper<StoStockInPlan> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("VIN",vin);
        queryWrapper.ne("BILL_STATE",2);
        queryWrapper.ne("BILL_STATE",3);
        List<StoStockInPlan> list = baseMapper.selectList(queryWrapper);
        List<StoStockInPlanVO> voList = new ArrayList<>();
        if(list == null || list.size() <= 0){
//            throw new Exception("操作失败,车辆:"+vin+"不存在待入库计划!");
            return voList;
        }
        voList = BeanTools.copyListToList(list, StoStockInPlanVO.class);
        for (int i = 0;i<list.size();i++){
            Date planStockInDate = list.get(i).getPlanStockInDate();
            if(planStockInDate != null){
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                String format = simpleDateFormat.format(planStockInDate);
                voList.get(i).setPlanStockInDate(format);
            }
        }*/
        return voList;
    }

    @Override
    public StoStockInPlanVO getDetailById(String id) throws Exception {
        return baseMapper.getDetailById(id);
    }

    /**
     * 通过VIN码找到新建的入库计划单
     * @param stoStockScanVO
     * @param vin
     * @return
     * @throws Exception
     */
    private StoStockInPlan getStockInOrderByVin(StoStockScanVO stoStockScanVO, String vin) throws Exception {
        QueryWrapper<StoStockInPlan> queryWrapper1 = new QueryWrapper();
        queryWrapper1.eq("VIN",vin);
        queryWrapper1.eq("BILL_STATE","0");
        StoStockInPlan stoStockInPlan = baseMapper.selectOne(queryWrapper1);
        if(stoStockInPlan == null){
            throw new Exception("操作失败,无法通过VIN码:"+stoStockScanVO.getVin()+"找到入库计划!");
        }
        return stoStockInPlan;
    }

    /**
     * 新增车辆RFID绑定历史
     * @param stoStockScanVO
     */
    private void newBindHistory(StoStockScanVO stoStockScanVO) {
        StoVrfidHistory stoVrfidHistory = new StoVrfidHistory();
        stoVrfidHistory.setVehicleRfid(stoStockScanVO.getVehicleRfid());
        stoVrfidHistory.setVin(stoStockScanVO.getVin());
        stoVrfidHistory.setBindType(1);//绑定
        stoVrfidHistory.setBindTime(new Date());
        stoVrfidHistoryService.saveOrUpdate(stoVrfidHistory);
    }

    /**
     * 变更库位冻结状态
     * @param isDel
     * @param stoStockInPlan
     */
    private void changeStorageFrozen(Integer isDel, StoStockInPlan stoStockInPlan) {
        QueryWrapper<StoManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("STORAGE_CODE",stoStockInPlan.getStorageCode());
        StoManage stoManage = stoManageService.getOne(queryWrapper);
        Integer isPositionFrozen = null;
        if(stoManage != null){
            isPositionFrozen = stoManage.getIsPositionFrozen();
            //恢复入库计划,如果库位未被冻结,则库位继续被该计划使用,冻结
            if(isDel.equals(0) && !isPositionFrozen.equals(1)){
                isPositionFrozen = 1;
            }
            //作废入库计划,则解冻该库位
            else if(isDel.equals(1)){
                isPositionFrozen = 0;
            }
            //恢复入库计划,如果库位已被冻结,则清空入库计划上的库位,需要重新分配
            else if(isDel.equals(0) && isPositionFrozen.equals(1)){
                stoStockInPlan.setStorageCode(null);
            }
            stoManage.setIsPositionFrozen(isPositionFrozen);
            stoManageService.saveOrUpdate(stoManage);
        }
    }
}
